/*
 * 代号：凤凰
 * http://www.jphenix.org
 * 2014-06-12
 * V4.0
 */
package com.jphenix.share.util;

import com.jphenix.share.lang.SDate;
import com.jphenix.share.lang.SDouble;
import com.jphenix.share.lang.SInteger;
import com.jphenix.share.lang.SString;
import com.jphenix.share.tools.Base64;
import com.jphenix.standard.docs.ClassInfo;
import com.jphenix.standard.viewhandler.IViewHandler;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Pattern;

/**
 * 字符串处理工具
 * 
 * 2018-06-05 增加了 从包含数字的字符串中提取出数字 getIntFromString
 * 2018-07-25 增加了将页面请求参数容器<String,String[]>转成普通的容器<String,String>
 * 2018-12-03 增加了返回指定长度的数字随机字符串
 * 2019-01-18 增加了数组转字符串方法，可以自定义分隔符
 * 2019-04-09 用SDouble替代了SFloat
 * 2019-08-01 节点_check属性值中可以包含多检测类型值，用|||分割
 * 2019-11-22 新增unicodeToStr方法，将转义的，比如\\u开头的字符串转义成真正的unicode值字符串
 * 2020-07-18 修改了将参数字符串转换为Map时，错误的过滤掉了空值的参数（随后不过滤空值参数）
 * 2022-01-27 增加了通过excel列索引返回列名的方法getExcelColumnName
 * 2022-06-22 修改了两个方法，将入参String[]改为Object[] 不影响原先使用
 * 2024-07-04 增加了补零和补空格方法
 * 
 * @author 刘虻 2007-6-22下午04:25:21
 */
@ClassInfo({ "2024-08-16 18:35", "字符串处理工具" })
public class StringUtil {

    /**
     * 字节0
     */
    public final static byte BYTE_0 = (byte) 48;

    /**
     * 字节1
     */
    public final static byte BYTE_1 = (byte) 49;

    public final static String ISO_8859_1 = "ISO-8859-1"; // ISO-8859-1

    /**
     * 编码类型
     */
    protected static final int sText = 0, s1Dig = 1, s2Dig = 2, sEscape = 3,
            sU1 = 4, sU2 = 5, sU3 = 6, sU4 = 7;

    //\ue04c 字符转换
	private static final String singlePattern = "[0-9|a-f|A-F]";
	private static final String pattern = singlePattern+singlePattern+singlePattern+singlePattern;

    /**
     * 根据当前时间获取随机字符串（末尾用0填充）
     * 
     * @author 刘虻 2007-6-22下午04:26:54
     * @param size
     *            字符串长度
     * @return 随机字符串
     */
    public static String getRndStringByTime(int size) {
        // 构建返回值
        StringBuffer reSbf = new StringBuffer(Long.toBinaryString(System
                .currentTimeMillis()));
        // 末尾填充0
        while (reSbf.length() < size) {
            reSbf.append("0");
        }
        return reSbf.toString();
    }

    /**
     * 获取两个二进制字符串的中间二进制值字符串 采用 小值+（大值-小值）/2
     * 
     * @author 刘虻 2007-6-22下午05:40:38
     * @param maxStr
     *            大二进制值
     * @param minStr
     *            小二进制值
     * @param size
     *            字符串长度
     * @return 中间二进制值
     */
    public static String getBinaryMiddleValue(String maxStr, String minStr,
            int size) {
        maxStr = SString.valueOf(maxStr);
        if ((maxStr == null || maxStr.length() == 0)
                && (minStr == null || minStr.length() == 0)) {
            return "";
        }
        if (maxStr == null) {
            // 获取一个比最小值大的值
            maxStr = getRndStringByTime(size);
            // 小+（大-小）/2
            return binaryStringAdd(minStr,
                    binaryStringDivsionTwo(binaryBytesSubtract(maxStr, minStr)));
        } else if (minStr == null) {
            minStr = maxStr;
            maxStr = getRndStringByTime(size);
            // 小-（大-小）/2
            return binaryStringAdd(minStr,
                    binaryStringDivsionTwo(binaryBytesSubtract(maxStr, minStr)));
        } else {
            // 小+（大-小）/2
            return binaryStringAdd(minStr,
                    binaryStringDivsionTwo(binaryBytesSubtract(maxStr, minStr)));
        }
    }

    /**
     * 两个二进制字符串值相加
     * 
     * @author 刘虻 2007-6-22下午05:44:51
     * @param srcBytes
     *            源二进制数组
     * @param addBytes
     *            累加二进制数组
     * @return 累加后的值
     */
    public static String binaryStringAdd(byte[] srcBytes, byte[] addBytes) {
        // 获取返回字节数组
        byte[] reBytes = binaryBytesAdd(srcBytes, addBytes);
        if (reBytes == null) {
            return null;
        }
        return new String(reBytes);
    }

    /**
     * 两个二进制字符串值相加
     * 
     * @author 刘虻 2007-6-23上午11:22:54
     * @param srcBytes
     *            源二进制数组
     * @param addBytes
     *            累加二进制数组
     * @return 累加后的二进制字节数组
     */
    public static byte[] binaryBytesAdd(byte[] srcBytes, byte[] addBytes) {
        if (srcBytes == null || addBytes == null) {
            return null;
        }
        int maxSize = 0; // 两个字符串中最长的字符串长度
        int srcByteSize = srcBytes.length; // 源数据长度
        int addByteSize = addBytes.length; // 累加数组长度
        if (srcByteSize > addByteSize) {
            maxSize = srcByteSize;
        } else {
            maxSize = addByteSize;
        }
        // 构造源数组和累加数组等长的数组
        byte[] fixSrcBytes = new byte[maxSize];
        if (maxSize > srcByteSize) {
            for (int i = maxSize - 1; i < maxSize - srcByteSize; i--) {
                fixSrcBytes[i] = BYTE_0;
            }
        }
        // 复制数组
        System.arraycopy(srcBytes, 0, fixSrcBytes, 0, srcByteSize);

        // 构造源数组和累加数组等长的数组
        byte[] fixAddBytes = new byte[maxSize];
        if (maxSize > addByteSize) {
            for (int i = maxSize - 1; i < maxSize - addByteSize; i--) {
                fixAddBytes[i] = BYTE_0;
            }
        }
        // 复制数组
        System.arraycopy(addBytes, 0, fixAddBytes, 0, addByteSize);
        // 构造返回值数组
        byte[] reBytes = new byte[maxSize];
        // 进位标识
        boolean carry = false;
        for (int i = maxSize - 1; i > -1; i--) {
            if (carry) {
                if (fixSrcBytes[i] == BYTE_1 && fixAddBytes[i] == BYTE_1) {
                    reBytes[i] = BYTE_1;
                } else if (fixSrcBytes[i] == BYTE_0 && fixAddBytes[i] == BYTE_0) {
                    reBytes[i] = BYTE_1;
                    carry = false;
                } else {
                    reBytes[i] = BYTE_0;
                }
            } else {
                if (fixSrcBytes[i] == BYTE_1 && fixAddBytes[i] == BYTE_1) {
                    carry = true;
                    reBytes[i] = BYTE_0;
                } else if (fixSrcBytes[i] == BYTE_0 && fixAddBytes[i] == BYTE_0) {
                    reBytes[i] = BYTE_0;
                } else {
                    reBytes[i] = BYTE_1;
                }
            }
        }
        return reBytes;

    }

    /**
     * 两个二进制字符串值相加
     * 
     * @author 刘虻 2007-6-22下午05:44:51
     * @param srcStr
     *            源二进制字符串值
     * @param addStr
     *            累加二进制字符串值
     * @return 累加后的值
     */
    public static String binaryStringAdd(String srcStr, String addStr) {
        if (srcStr == null || addStr == null) {
            return null;
        }
        return binaryStringAdd(srcStr.getBytes(), addStr.getBytes());
    }

    /**
     * 两个二进制字符串值相加
     * 
     * @author 刘虻 2007-6-23上午11:26:37
     * @param srcStr
     *            源二进制字符串值
     * @param addStr
     *            累加二进制字符串值
     * @return 累加后的二进制数组
     */
    public static byte[] binaryBytesAdd(String srcStr, String addStr) {
        if (srcStr == null || addStr == null) {
            return null;
        }
        return binaryBytesAdd(srcStr.getBytes(), addStr.getBytes());
    }

    /**
     * 两个二进制字符串值相减 注意：只能大值减小值
     * 
     * @author 刘虻 2007-6-22下午07:07:24
     * @param maxStr
     *            大值
     * @param minStr
     *            小值
     * @return 相减以后的值
     */
    public static String binaryStringSubtract(String maxStr, String minStr) {
        if (maxStr == null || minStr == null) {
            return null;
        }
        return binaryStringSubtract(maxStr.getBytes(), minStr.getBytes());
    }

    /**
     * 去掉源字符串末尾符合要求的字符
     * @author 刘虻 2009-8-17上午12:45:04
     * @param srcStr 源字符串
     * @param cutStr 待去掉的字符串
     * @return 处理后的字符串
     */
    public static String cutEndStr(String srcStr, String cutStr) {
        if (srcStr == null) {
            return "";
        }
        if (cutStr == null) {
            return srcStr;
        }
        if (srcStr.endsWith(cutStr)) {
            return cutEndStr(srcStr.substring(0, cutStr.length()), cutStr);
        }
        return srcStr;
    }

    /**
     * 去掉源字符串开头符合要求的字符
     * @author 刘虻 2009-8-17上午12:45:04
     * @param srcStr 源字符串
     * @param cutStr 待去掉的字符串
     * @return 处理后的字符串
     */
    public static String cutStartStr(String srcStr, String cutStr) {
        if (srcStr == null) {
            return "";
        }
        if (cutStr == null) {
            return srcStr;
        }
        if (srcStr.startsWith(cutStr)) {
            return cutStartStr(srcStr.substring(cutStr.length()), cutStr);
        }
        return srcStr;
    }

    /**
     * 两个二进制字符串相减 注意：只能大值减小值
     * 
     * @author 刘虻 2007-6-23上午11:38:55
     * @param maxStr
     *            大值
     * @param minStr
     *            小值
     * @return 相减后的值
     */
    public static byte[] binaryBytesSubtract(String maxStr, String minStr) {
        if (maxStr == null || minStr == null) {
            return null;
        }
        return binaryBytesSubtract(maxStr.getBytes(), minStr.getBytes());
    }

    /**
     * 将字母转换为数字(不区分大小写） A=0 B=1 Z=25
     * 
     * @author 刘虻 2007-8-20下午07:39:00
     * @param letter
     *            输入值
     * @return 转换后值
     */
    public static int letterToNumberZero(String letter) {
        // 获取从1开始算的值
        int reInt = letterToNumber(letter);
        if (reInt > 0) {
            return reInt - 1;
        }
        return reInt;
    }

    /**
     * 将变量中的html内容经过整理,输出到html页面的textarea中
     * 
     * @author 刘虻 2007-10-12下午07:59:18
     * @param html
     *            内容
     * @return 整理后的内容
     */
    public static String fixOutHtmlToTextarea(String html) {
        if (html == null) {
            return null;
        }
        return html.replaceAll("(\\&)", "&amp;")
                .replaceAll("(?i)<textarea", "&lt;textarea")
                .replaceAll("(?i)</textarea", "&lt;/textarea");
    }

    /**
     * 处理html内容 将敏感字符替换成安全字符
     * 
     * @author 刘虻 2007-10-17下午05:53:03
     * @param html
     *            源html内容
     * @return 处理后的html内容
     */
    public static String fixHtmlString(String html) {
        if (html == null) {
            return null;
        }
        return html.replaceAll("(\\&)", "&amp;").replaceAll("(\\#)", "&#35;")
                .replaceAll("(\\?)", "&#63;").replaceAll("(\\%)", "&#37;")
                .replaceAll("(?i)<", "&lt;").replaceAll("(?i)>", "&gt;")
                .replaceAll("(?i) ", "&nbsp;")
                .replaceAll("(?i)\\r\\n", "<br />")
                .replaceAll("(?i)\\r", "<br />")
                .replaceAll("(?i)\\n", "<br />");
    }

    /**
     * 将html内容转换为字符串类型
     * 
     * @author 刘虻 2007-10-22下午07:57:20
     * @param html
     *            html内容
     * @return 转换后的字符串
     */
    public static String unFixHtmlString(String html) {
        if (html == null) {
            return null;
        }
        return html.replaceAll("(?i)&amp;", "&").replaceAll("(?i)&#35;", "#")
                .replaceAll("(?i)&#63;", "?").replaceAll("(?i)&#37;", "%")
                .replaceAll("(?i)&lt;", "<").replaceAll("(?i)&gt;", ">")
                .replaceAll("(?i)&nbsp;", " ").replaceAll("(?i)<br>", "\r\n")
                .replaceAll("(?i)<br/>", "\r\n")
                .replaceAll("(?i)<br />", "\r\n");
    }

    /**
     * 获取URL编码字符串
     * 
     * @author 刘虻 2007-11-8下午07:46:53
     * @param srcStr
     *            源字符串
     * @return 编码后的字符串
     */
    public static String getURLEncoding(String srcStr) {
        return getURLEncoding(srcStr, null);
    }

    /**
     * 获取URL编码字符串
     * 
     * @author 刘虻 2009-1-12上午11:17:05
     * @param srcStr
     *            原字符串
     * @param enc
     *            编码字符串
     * @return URL编码后的字符串
     */
    public static String getURLEncoding(String srcStr, String enc) {
        if (srcStr == null) {
            return "";
        }
        if (enc == null || enc.length() < 1) {
            enc = "UTF-8";
        }
        try {
            return URLEncoder.encode(srcStr, enc);
        } catch (Exception e) {
            return srcStr;
        }
    }

    /**
     * 获取URL解码字符串
     * 
     * @author 刘虻 2009-1-12上午11:18:58
     * @param urlStr
     *            url字符串
     * @param enc
     *            字符串编码
     * @return 解码字符串
     */
    public static String getURLDecoding(String urlStr, String enc) {
        if (urlStr == null) {
            return "";
        }
        if (enc == null || enc.length() < 1) {
            enc = "UTF-8";
        }
        try {
            return URLDecoder.decode(urlStr, enc);
        } catch (Exception e) {
            return urlStr;
        }
    }

    /**
     * 获取URL解码字符串
     * 
     * @author 刘虻 2009-1-12上午11:20:03
     * @param urlStr
     *            url字符串
     * @return 解码字符串
     */
    public static String getURLDecoding(String urlStr) {
        return getURLDecoding(urlStr, null);
    }

    /**
     * 将字母转换为数字(不区分大小写）
     * 
     * 如：A=1 B=2 Z=26 AA=27 AB=28
     * 
     * @author 刘虻 2007-8-13下午01:04:34
     * @param letter
     *            输入值
     * @return 转换后值
     */
    public static int letterToNumber(String letter) {
        if (letter == null || letter.length() == 0) {
            return 0;
        }
        // 转换为大写字母
        letter = letter.toUpperCase();

        // 获取字符串长度
        int length = letter.length();
        // 1 23 123 5234
        // 10X0+1 20X2+3 10X10X1+10X2+3 10X10X10X5+10X10X2+10X3+4
        // 构造返回值
        int reInt = 0;
        // 循环处理值
        for (int i = 0; i < length; i++) {
            // 获取字符
            int element = (letter.charAt(i)) - 64;
            // 位
            int point = length - i;
            // 本位值
            int value = 1;
            if (point == 1) {
                value = 0;
            } else {
                for (int j = 0; j < point - 1; j++) {
                    value = value * 26;
                }
            }
            if (i == length - 1) {
                reInt += value + element;
            } else {
                reInt += value * element;
            }
        }
        return reInt;
    }

    /**
     * 数字转换为对应的字符,从0开始 比如 0=A 1=B 25=Z 26=AA
     * 
     * @author 刘虻 2008-12-28下午03:24:14
     * @param num
     *            指定数字
     * @return 对应字符
     */
    public static String numberZeroToLetter(int num) {
        return numberZeroToLetter(num, "");
    }

    /**
     * 数字转换为对应的字符 比如 1=A 2=B 26=Z 27=AA
     * 
     * @author 刘虻 2008-12-28下午03:24:14
     * @param num
     *            指定数字
     * @return 对应字符
     */
    public static String numberToLetter(int num) {
        return numberZeroToLetter(--num, "");
    }

    /**
     * 数字转换为对应的字符（递归处理函数）
     * 
     * @author 刘虻 2008-12-28下午03:25:32
     * @param num
     *            指定数字
     * @param headLetter
     *            已经生成的头字符串
     * @return 处理后的字符串
     */
    protected static String numberZeroToLetter(int num, String headLetter) {
        int hNum = num / 26; // 获取是否大于一位
        int lNum = num % 26; // 获取余数
        if (hNum > 0) {
            headLetter += numberZeroToLetter(hNum - 1, headLetter);
        }

        headLetter += String.valueOf((char) (lNum + 65));

        return headLetter;
    }

    /**
     * 获取编码的字符串
     * 
     * 将 http://www.web.com/aa?key=测试 转换为 http://www.web.com/aa?key=%B9%FE%B0%A1
     * 
     * @author 刘虻 2008-4-17下午05:59:12
     * @param url
     * @return
     */
    public static String getUrlEncodingParameterString(String url) {
        if (url == null) {
            return "";
        }
        return getURLEncoding(url).replaceAll("%2F", "/")
                .replaceAll("%3A", ":").replaceAll("%3F", "?")
                .replaceAll("%3D", "=").replaceAll("%26", "&");
    }

    /**
     * 将二进制字符串除以2 原理：将字符串右移
     * 
     * @author 刘虻 2007-6-22下午07:33:28
     * @param srcStr
     *            源二进制字符串
     * @return 除以2后的值
     */
    public static String binaryStringDivsionTwo(String srcStr) {
        if (srcStr == null) {
            return null;
        }
        return binaryStringDivsionTwo(srcStr.getBytes());
    }

    /**
     * 将二进制字符串除以2
     * 
     * @author 刘虻 2007-6-23上午11:45:23
     * @param srcStr
     *            源二进制字符串
     * @return 除以2后的二进制数组
     */
    public static byte[] binaryBytesDivsionTwo(String srcStr) {
        if (srcStr == null) {
            return null;
        }
        return binaryBytesDivsionTwo(srcStr.getBytes());
    }

    /**
     * 将二进制数组串除以2
     * 
     * @author 刘虻 2007-6-22下午07:33:28
     * @param srcBytes
     *            源二进制数组
     * @return 除以2后的值
     */
    public static String binaryStringDivsionTwo(byte[] srcBytes) {
        // 构造返回值字节数组
        byte[] reBytes = binaryBytesDivsionTwo(srcBytes);
        if (reBytes == null) {
            return null;
        }
        return new String(reBytes);
    }

    /**
     * 将二进制数组值除以2
     * 
     * @author 刘虻 2007-6-23上午11:43:23
     * @param srcBytes
     *            源二进制数组
     * @return 除以2的值
     */
    public static byte[] binaryBytesDivsionTwo(byte[] srcBytes) {
        if (srcBytes == null) {
            return null;
        }
        byte[] reBytes = new byte[srcBytes.length];

        // 最高位设置为0
        reBytes[srcBytes.length - 1] = BYTE_0;
        for (int i = 0; i < srcBytes.length - 1; i++) {
            reBytes[i] = srcBytes[i];
        }
        return reBytes;
    }

    /**
     * 两个二进制字符串值相减 注意：只能大值减小值
     * 
     * @author 刘虻 2007-6-23上午11:34:11
     * @param maxBytes
     *            大值
     * @param minBytes
     *            小值
     * @return 差值字节数组
     */
    public static byte[] binaryBytesSubtract(byte[] maxBytes, byte[] minBytes) {
        if (maxBytes == null || minBytes == null) {
            return null;
        }
        int maxLengthSize = 0; // 两个字符串中最长的字符串长度
        int maxBytesSize = maxBytes.length; // 大值长度
        int addByteSize = minBytes.length; // 小值长度
        if (maxBytesSize > addByteSize) {
            maxLengthSize = maxBytesSize;
        } else {
            maxLengthSize = addByteSize;
        }
        // 构造源数组和累加数组等长的数组
        byte[] fixMaxBytes = new byte[maxLengthSize];
        if (maxLengthSize > maxBytesSize) {
            for (int i = maxLengthSize - 1; i < maxLengthSize - maxBytesSize; i--) {
                fixMaxBytes[i] = BYTE_0;
            }
        }
        // 复制数组
        System.arraycopy(maxBytes, 0, fixMaxBytes, 0, maxBytesSize);

        // 构造源数组和累加数组等长的数组
        byte[] fixMinBytes = new byte[maxLengthSize];
        if (maxLengthSize > addByteSize) {
            for (int i = maxLengthSize - 1; i < maxLengthSize - addByteSize; i--) {
                fixMinBytes[i] = BYTE_0;
            }
        }
        // 复制数组
        System.arraycopy(minBytes, 0, fixMinBytes, 0, addByteSize);
        // 构造返回值数组
        byte[] reBytes = new byte[maxLengthSize];
        // 借位标识
        boolean carry = false;
        for (int i = maxLengthSize - 1; i > -1; i--) {

            if (fixMaxBytes[i] == BYTE_1 && fixMinBytes[i] == BYTE_0) {

                if (carry) {
                    carry = false;
                    reBytes[i] = BYTE_0;
                } else {
                    reBytes[i] = BYTE_1;
                }

            } else if (fixMaxBytes[i] == BYTE_0 && fixMinBytes[i] == BYTE_1) {
                if (carry) {
                    reBytes[i] = BYTE_0;
                } else {
                    reBytes[i] = BYTE_1;
                    carry = true;
                }
            } else if (fixMaxBytes[i] == BYTE_0 && fixMinBytes[i] == BYTE_0) {
                if (carry) {
                    reBytes[i] = BYTE_1;
                } else {
                    reBytes[i] = BYTE_0;
                }
            } else {
                if (carry) {
                    reBytes[i] = BYTE_1;
                } else {
                    reBytes[i] = BYTE_0;
                }
            }
        }
        return reBytes;
    }

    /**
     * 两个二进制字符串值相减 注意：只能大值减小值
     * 
     * @author 刘虻 2007-6-22下午07:07:24
     * @param maxBytes
     *            大值
     * @param minBytes
     *            小值
     * @return 相减以后的值
     */
    public static String binaryStringSubtract(byte[] maxBytes, byte[] minBytes) {
        // 构造返回值字节数组
        byte[] reBytes = binaryBytesSubtract(maxBytes, minBytes);
        if (reBytes == null) {
            return null;
        }
        return new String(reBytes);
    }

    /**
     * 源二进制字符串比目标二进制字符串大 返回真
     * 
     * @author 刘虻 2007-6-22下午05:01:39
     * @param srcStr
     *            源二进制字符串
     * @param objStr
     *            目标二进制字符串
     * @return 源比目标大返回真
     */
    public static boolean binaryCompare(String srcStr, String objStr) {
        if (srcStr == null || objStr == null) {
            return false;
        }
        return binaryCompare(srcStr.getBytes(), objStr.getBytes());
    }

    /**
     * 比较两个二进制数组大小
     * 
     * @author 刘虻 2007-6-22下午06:40:54
     * @param srcBytes
     *            源二进制数组
     * @param objBytes
     *            比较二进制数组
     * @return true源二进制数组大
     */
    public static boolean binaryCompare(byte[] srcBytes, byte[] objBytes) {
        if (srcBytes == null || objBytes == null) {
            return false;
        }
        int srcByteSize = srcBytes.length; // 原字符串位数
        int objByteSize = objBytes.length; // 目标字符串位数
        if (srcByteSize > objByteSize) {
            // 源数组比比较数组长/判断比比较数组长的部分有没有1值，如果有，直接返回真
            for (int i = srcByteSize - 1; i < srcByteSize - objByteSize; i--) {
                if (srcBytes[i] == BYTE_1) {
                    return true;
                }
            }
            return false;
        }
        int subtractValue = 0; // 差值
        for (int i = srcByteSize - 1; i > -1; i--) {
            subtractValue = srcBytes[i] - objBytes[i];
            if (subtractValue != 0) {
                break;
            }
        }
        return subtractValue == 1;
    }

    /**
     * 将页面请求，提交参数转换为静态文件名（不带扩展名，带相对路径（相对网站根路径））
     * 
     * @param uri
     *            页面请求 使用 getServletPath 获取
     * @param queryString
     *            URL中提交参数
     * @param isCheck
     *            获取到的静态页面路径用于校验，如果提交参数中包含了 __sp__=__sp__，就返回空
     * @return 静态文件名 2014年12月11日
     * @author 马宝刚
     */
    public static String toStaticPageName(String uri, String queryString,
            boolean isCheck) {
        int point; // 分割点
        if (uri == null) {
            // 麻痹如果真的出现这种情况，纯粹是故意的
            return null;
        } else {
            // 动作扩展名
            point = uri.lastIndexOf(".");
            if (point > 0) {
                uri = uri.substring(0, point);
            }
        }
        if (queryString != null) {
            point = queryString.indexOf("__sp__=__sp__");
            if (point > -1) {
                if (isCheck) {
                    return null;
                }
                // 后半段
                String afterStr = queryString.substring(point + 13
                );
                if (afterStr.startsWith("&")) {
                    afterStr = afterStr.substring(1);
                }
                queryString = queryString.substring(0, point) + afterStr;
            }
            uri += "_" + queryString.replaceAll("%", "_").replaceAll("=", "-");
        }
        return uri;
    }

    /**
     * 获取html中的文本内容
     * 
     * @author 刘虻 2009-2-4下午02:59:30
     * @param source
     *            html内容
     * @return 文本内容
     */
    public static String getHtmlText(String source) {
        return cutHtmlReturnText(source, -1, null);
    }

    /**
     * 将html内容转换为文本内容，并针对文本内容截取字符串
     * 
     * @author 刘虻 2009-2-4下午02:57:01
     * @param source
     *            html内容
     * @param cutSize
     *            截取字符数
     * @param footStr
     *            截取后在结尾增加的字符串
     * @return 处理后的字符串
     */
    public static String cutHtmlReturnText(String source, int cutSize,
            String footStr) {
        if (source == null) {
            return "";
        }
        if (footStr == null) {
            footStr = "";
        }
        int length = source.length(); // 内容长度
        if (cutSize < 1 || length < cutSize) {
            cutSize = length;
        }
        if (source.indexOf("<") < 0) {
            if (source.length() > cutSize) {
                return source.substring(0, cutSize) + footStr;
            }
            return source;
        }
        // 是否需要截取
        boolean needCut = false;
        // 读取位置
        int readPoint = 0;
        // 构造返回值
        StringBuffer reSbf = new StringBuffer();
        int tPoint = 0; // 标签标志数
        for (int i = 0; i < length; i++) {
            // 获取一个字符
            String oneChar = source.substring(i, i + 1);
            if ("<".equals(oneChar)) {
                tPoint++;
                continue;
            } else if (">".equals(oneChar)) {
                tPoint--;
                continue;
            }
            if (tPoint == 0) {
                reSbf.append(oneChar);
                readPoint++;
                if (readPoint > cutSize) {
                    needCut = true;
                    break;
                }
            }
        }
        if (needCut) {
            return unFixHtmlString(reSbf.append(footStr).toString());
        }
        return unFixHtmlString(reSbf.toString());
    }

    /**
     * 限制字符串长度（不算html代码）
     * 
     * @author 刘虻 2007-10-15下午08:02:28
     * @param source 源html字符串
     * @param cutSize 限制长度
     * @param footStr 限制后附加字符串
     * @return 处理后的字符串
     */
    public static String cutHtmlString(String source, int cutSize,
            String footStr) {
        if (source == null) {
            return "";
        }
        if (footStr == null) {
            footStr = "";
        }
        int length = source.length();
        if (length <= cutSize) {
            return source;
        }

        if (source.indexOf("<") < 0) {
            return source.substring(0, cutSize) + footStr;
        }
        int readPoint = 0;
        // 构造返回值
        StringBuffer reSbf = new StringBuffer();
        boolean isAppend = true; // 是否累加
        boolean notAppendFoot = true; // 是否没放入尾部
        boolean insideTag = false; // 是否为标签内部
        boolean onOutTag = false; // 是否为结束字符
        for (int i = 0; i < length; i++) {
            // 获取一个字符
            String oneChar = source.substring(i, i + 1);
            if ("<".equals(oneChar)) {
                insideTag = true;
            } else if (">".equals(oneChar)) {
                insideTag = false;
                onOutTag = true;
            } else if (!insideTag) {
                readPoint++;
            }
            if (readPoint > cutSize) {
                isAppend = insideTag;
                if (notAppendFoot) {
                    reSbf.append(footStr);
                    notAppendFoot = false;
                }
            }
            if (isAppend || onOutTag) {
                if (onOutTag) {
                    onOutTag = false;
                }
                reSbf.append(oneChar);
            }
        }
        return reSbf.toString().replaceAll("<br/>", "").replaceAll("<br>", "");
    }

    /**
     * 母鸡
     * 
     * @author 刘虻 2008-7-9上午07:45:10
     * @param s
     *            母鸡
     * @param encodeWS
     *            母鸡
     * @return 母鸡
     */
    public static String htmlEncode(String s, boolean encodeWS) {
        if (s == null) {
            return null;
        }
        char[] ca = s.toCharArray();
        StringBuffer res = new StringBuffer(ca.length);
        int ls = 0;
        boolean blankMet = true;
        for (int i = 0; i < ca.length; i++) {
            switch (ca[i]) {
            case '<':
                res.append(ca, ls, i - ls);
                res.append("&lt;");
                ls = i + 1;
                break;
            case '>':
                res.append(ca, ls, i - ls);
                res.append("&gt;");
                ls = i + 1;
                break;
            case '"':
                res.append(ca, ls, i - ls);
                res.append("&quot;");
                ls = i + 1;
                break;
            case '&':
                res.append(ca, ls, i - ls);
                res.append("&amp;");
                ls = i + 1;
                break;
            case ' ':
                if (blankMet && encodeWS) {
                    res.append(ca, ls, i - ls);
                    res.append("&nbsp;");
                    ls = i + 1;
                } else {
                    blankMet = true;
                }
                break;
            case '\n':
                if (encodeWS) {
                    res.append(ca, ls, i - ls);
                    res.append("<BR>");
                    ls = i + 1;
                }
                break;
            case '\r':
                if (encodeWS) {
                    res.append(ca, ls, i - ls);
                    ls = i + 1;
                }
                break;
            default:
                if (ca[i] > 127) { // no unicode
                    res.append(ca, ls, i - ls);
                    res.append("&#;" + (int) ca[i]);
                    ls = i + 1;
                }
                blankMet = false;
            }
        }
        if (ls < ca.length) {
            res.append(ca, ls, ca.length - ls);
        }
        return res.toString();
    }

    /**
     * URL解码
     * 
     * @author 刘虻 2008-7-9上午07:43:36
     * @param s
     *            源字符串
     * @param enc
     *            编码格式
     * @return 解码后的字符串
     * @throws UnsupportedEncodingException
     *             执行发生异常
     */
    public static String decode(String s, String enc)
            throws UnsupportedEncodingException {
        boolean decoded = false;
        int l = s.length();
        StringBuffer sb = new StringBuffer(l > 1024 ? l / 3 : l);
        int state = sText;
        int i = 0;
        int code = 0;
        char c;
        int pos = 0;
        int ofs = 0;
        byte[] buf = null;
        boolean processDig = false;
        while (i < l) {
            c = s.charAt(i);
            switch (c) {
            case '+':
                decoded = true;
                if (state == sText) {
                    sb.append(' ');
                } else if (state == s2Dig) {
                    sb.append(new String(buf, 0, pos + 1, enc));
                    state = sText;
                    sb.append(' ');
                } else {
                    new IllegalArgumentException(
                            "decode: unexpected + at pos: " + i + ", of : " + s);
                }
                break;
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
                ofs = '0';
                processDig = true;
                break;
            case 'a':
            case 'b':
            case 'c':
            case 'd':
            case 'e':
            case 'f':
                ofs = 'a' - 10;
                processDig = true;
                break;
            case 'A':
            case 'B':
            case 'C':
            case 'D':
            case 'E':
            case 'F':
                ofs = 'A' - 10;
                processDig = true;
                break;
            case '%':
                decoded = true;
                if (state == sText) {
                    state = sEscape;
                    if (buf == null) {
                        buf = new byte[(l - i) / 3];
                    }
                    pos = 0;
                } else if (state == s2Dig) {
                    state = sEscape;
                    pos++;
                } else {
                    new IllegalArgumentException(
                            "decode: unexpected escape % at pos: " + i
                                    + ", of : " + s);
                }
                break;
            case 'u':
                if (state == sEscape) {
                    if (pos > 0) {
                        sb.append(new String(buf, 0, pos, enc));
                        pos = 0;
                    }
                    state = sU1;
                } else if (state == sText) {
                    sb.append(c);
                } else if (state == s2Dig) {
                    sb.append(new String(buf, 0, pos + 1, enc));
                    state = sText;
                    sb.append(c);
                } else {
                    new IllegalArgumentException(
                            "decode: unexpected char in hex at pos: " + i
                                    + ", of : " + s);
                }
                break;
            default:
                if (state == sText) {
                    sb.append(c);
                } else if (state == s2Dig) {
                    sb.append(new String(buf, 0, pos + 1, enc));
                    state = sText;
                    sb.append(c);
                } else {
                    new IllegalArgumentException(
                            "decode: unexpected char in hex at pos: " + i
                                    + ", of : " + s);
                }

                break;
            }
            i++;
            if (processDig) {
                if (state == sEscape) {
                    code = c - ofs;
                    state = s1Dig;
                } else if (state == s1Dig) {
                    buf[pos] = (byte) (code * 16 + (c - ofs));
                    state = s2Dig;
                } else if (state == s2Dig) { // escape finished
                    sb.append(new String(buf, 0, pos + 1, enc));
                    state = sText;
                    sb.append(c);
                } else if (state == sU1) {
                    code = c - ofs;
                    state = sU2;
                } else if (state == sU2) {
                    code = code * 16 + c - ofs;
                    state = sU3;
                } else if (state == sU3) {
                    code = code * 16 + c - ofs;
                    state = sU4;
                } else if (state == sU4) {
                    sb.append((char) (code * 16 + c - ofs));
                    state = sText;
                } else {
                    sb.append(c);
                }
                processDig = false;
            }
        }
        if (state == s2Dig) {
            sb.append(new String(buf, 0, pos + 1, enc));
        }
        return (decoded ? sb.toString() : s);
    }

    /**
     * 分割字符串 默认分隔符
     * 
     * @author 刘虻 2008-2-20下午02:49:07
     * @param str
     *            源字符串
     * @return 分割后的数组
     */
    public static String[] splitStr(String str) {
        StringTokenizer st = new StringTokenizer(str);
        int n = st.countTokens();
        String[] strs = new String[n];
        for (int i = 0; i < n; ++i) {
            strs[i] = st.nextToken();
        }
        return strs;
    }

    /**
     * 分割字符串
     * 
     * @author 刘虻 2008-2-20下午02:49:48
     * @param str
     *            源字符串
     * @param delim
     *            分隔符
     * @return 分割后的数组
     */
    public static String[] splitStr(String str, char delim) {
        int n = 1;
        int index = -1;
        while (true) {
            index = str.indexOf(delim, index + 1);
            if (index == -1) {
                break;
            }
            ++n;
        }
        String[] strs = new String[n];
        index = -1;
        for (int i = 0; i < n - 1; ++i) {
            int nextIndex = str.indexOf(delim, index + 1);
            strs[i] = str.substring(index + 1, nextIndex);
            index = nextIndex;
        }
        strs[n - 1] = str.substring(index + 1);
        return strs;
    }

    /**
     * 分割字符串
     * 
     * @author 刘虻 2008-7-9上午07:46:15
     * @param str
     *            源字符串
     * @param quotes
     *            分隔符
     * @return 分割后的数组
     */
    public static String[] splitStr(String str, String quotes) {
        char[] ca = str.toCharArray();
        // List result = new ArrayList(10);
        String[] result = new String[0];
        boolean inArg = false;
        boolean quoted = false;
        int argStart = -1;
        for (int i = 0; i < ca.length; i++) {
            char c = ca[i];
            if (inArg) {
                if (quoted) {
                    if (quotes.indexOf(c) >= 0) {
                        result = copyOf(result, result.length + 1);
                        result[result.length - 1] = new String(ca, argStart, i
                                - argStart);
                        argStart = -1;
                        quoted = false;
                        inArg = false;
                    }
                } else {
                    if (c == ' ') {
                        result = copyOf(result, result.length + 1);
                        result[result.length - 1] = new String(ca, argStart, i
                                - argStart);
                        argStart = -1;
                        inArg = false;
                    }
                }
            } else {
                if (c != ' ') {
                    inArg = true;
                    if (quotes.indexOf(c) >= 0) {
                        quoted = true;
                        argStart = i + 1;
                    } else {
                        argStart = i;
                    }
                }
            }
        }
        if (argStart > 0) {
            result = copyOf(result, result.length + 1);
            result[result.length - 1] = new String(ca, argStart, ca.length
                    - argStart);
        }
        return result;
    }
    
    
    /**
     * 通过参数容器转换参数字符串（除去空参数）
     * 
     * @author 刘虻 2008-8-27上午11:00:23
     * @param paraMap
     *            参数容器
     * @return 参数字符串
     */
    @SuppressWarnings("rawtypes")
    public static String getParaStringFromMapPro(Map paraMap) {
        // 构造返回值
        StringBuffer reSbf = new StringBuffer();

        if (paraMap == null) {
            return "";
        }
        boolean noFirstPara = false; // 是否不是第一个参数
        // 获取主键对象
        Set keySet = paraMap.keySet();
        if (keySet == null) {
            return "";
        }
        // 获取主键迭代
        Iterator keyIterator = keySet.iterator();
        if (keyIterator == null) {
            return "";
        }
        while (keyIterator.hasNext()) {
            // 获取主键
            String key = (String) keyIterator.next();
            if (key == null) {
                continue;
            }
            // 获取主键值
            Object valueObj = paraMap.get(key);
            if (valueObj == null) {
                continue;
            }
            String value = null; // 主键字符串值
            if (valueObj instanceof String[]) {
                if (((String[]) valueObj).length > 0) {
                    value = SString.valueOf(((String[]) valueObj)[0]);
                } else {
                    value = "";
                }
            } else {
                value = SString.valueOf(valueObj);
            }
            if(value.length()<1) {
                continue;
            }
            if (noFirstPara) {
                reSbf.append("&");
            }
            noFirstPara = true;
            reSbf.append(key).append("=").append(getURLEncoding(value));
        }
        return reSbf.toString();
    }

    /**
     * 通过参数容器转换参数字符串
     * 
     * @author 刘虻 2008-8-27上午11:00:23
     * @param paraMap
     *            参数容器
     * @return 参数字符串
     */
    @SuppressWarnings("rawtypes")
    public static String getParaStringFromMap(Map paraMap) {
        // 构造返回值
        StringBuffer reSbf = new StringBuffer();

        if (paraMap == null) {
            return "";
        }
        boolean noFirstPara = false; // 是否不是第一个参数
        // 获取主键对象
        Set keySet = paraMap.keySet();
        if (keySet == null) {
            return "";
        }
        // 获取主键迭代
        Iterator keyIterator = keySet.iterator();
        if (keyIterator == null) {
            return "";
        }
        while (keyIterator.hasNext()) {
            // 获取主键
            String key = (String) keyIterator.next();
            if (key == null) {
                continue;
            }
            // 获取主键值
            Object valueObj = paraMap.get(key);
            if (valueObj == null) {
                continue;
            }
            String value = null; // 主键字符串值
            if (valueObj instanceof String[]) {
                if (((String[]) valueObj).length > 0) {
                    value = SString.valueOf(((String[]) valueObj)[0]);
                } else {
                    value = "";
                }
            } else {
                value = SString.valueOf(valueObj);
            }
            if (noFirstPara) {
                reSbf.append("&");
            }
            noFirstPara = true;
            reSbf.append(key).append("=").append(getURLEncoding(value));
        }
        return reSbf.toString();
    }
    
    /**
     * 将页面请求的容器转换为普通参数容器
     * @param pMap    页面请求容器
     * @return        普通参数容器
     * 2018年7月24日
     * @author MBG
     */
    public static Map<String,String> getSingleParameterMap(Map<String,String[]> pMap){
    	//构造返回值
    	Map<String,String> reMap = new HashMap<String,String>();
    	if(pMap!=null) {
    		//主键迭代器
    		Iterator<String> keyIterator = pMap.keySet().iterator();
    		String key;       //主键
    		String[] values;  //值
    		while(keyIterator.hasNext()) {
    			key = keyIterator.next();
    			if(key==null || key.length()<1) {
    				continue;
    			}
    			values = pMap.get(key);
    			if(values==null || values.length<1 || values[0]==null) {
    				continue;
    			}
    			reMap.put(key,values[0]);
    		}
    	}
    	return reMap;
    }

    /**
     * 通过参数字符串转换参数容器
     * 
     * @author 刘虻 2008-8-27上午10:59:23
     * @param paraStr
     *            参数字符串 pa=va&pb=vb&bc=vc
     * @return 参数容器 key 参数主键 value 参数值
     */
    public static Map<String, String> getParaMapFromString(String paraStr) {
        // 构建返回值
        HashMap<String, String> reMap = new HashMap<String, String>();
        if (paraStr == null) {
            return reMap;
        }
        // 获取参数序列
        String[] paras = paraStr.split("&");
        if (paras == null) {
            return reMap;
        }
        for (int i = 0; i < paras.length; i++) {
            if (paras[i] == null) {
                continue;
            }
            // 分割参数
            String[] paraSubs = paras[i].split("=");
            if (paraSubs == null || paraSubs.length < 1) {
                continue;
            }else if(paraSubs.length<2) {
                // 放入参数容器
                reMap.put(paraSubs[0],"");
            }else {
                // 放入参数容器
                reMap.put(paraSubs[0], getURLDecoding(paraSubs[1]));
            }
        }
        return reMap;
    }
    
   

    /**
     * 过滤掉字符串中非数字字符
     * 
     * @author 刘虻 2008-8-29下午05:47:29
     * @param numberStr
     *            待过滤字符串
     * @return 过滤后的字符串
     */
    public static String fixNumberString(String numberStr) {

        if (numberStr == null || numberStr.length() < 1) {
            return "0";
        }
        // 构建返回值
        StringBuffer reSbf = new StringBuffer();

        boolean noPoint = true; // 是否不存在小数点

        for (int i = 0; i < numberStr.length(); i++) {
            // 获取一个字符
            String str = numberStr.substring(i, i + 1);

            if (i == 0 && "-".equals(str)) {
                reSbf.append(str);
            } else if (noPoint && ".".equals(str)) {
                noPoint = false;
                reSbf.append(str);
            } else if ("0".equals(str) || "1".equals(str) || "2".equals(str)
                    || "3".equals(str) || "4".equals(str) || "5".equals(str)
                    || "6".equals(str) || "7".equals(str) || "8".equals(str)
                    || "9".equals(str)) {
                reSbf.append(str);
            }
        }
        return reSbf.toString();
    }

    /**
     * 复制数组
     * 
     * @author 刘虻 2008-7-9上午07:46:42
     * @param original
     *            母鸡
     * @param newLength
     *            母鸡
     * @return 母鸡
     */
    public static String[] copyOf(String[] original, int newLength) {
        String[] copy = new String[newLength];
        System.arraycopy(original, 0, copy, 0,
                Math.min(original.length, newLength));
        return copy;
    }

    /**
     * 将字符串转换为I18n格式字符串
     * 
     * @author 刘虻 2008-12-18下午06:17:10
     * @param srcStr
     *            源字符串
     * @return I18n 格式字符串
     */
    public static String getI18nString(String srcStr) {
        if (srcStr == null) {
            return "";
        }
        // 构建返回值
        StringBuffer reSbf = new StringBuffer();

        // 分解为字符数组
        char[] chars = srcStr.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            reSbf.append(native2Ascii(chars[i]));
        }
        return reSbf.toString();
    }

    /**
     * 将I18n字符串转换为普通字符串
     * 
     * @author 刘虻 2008-12-25下午07:10:02
     * @param i18nStr
     *            I18n字符串
     * @return 普通字符串
     */
    public static String fromI18nString(String i18nStr) {
        try {
            return new String(ascii2Native(i18nStr).getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 将字符转换为I81n格式
     * 
     * @author 刘虻 2008-12-18下午06:15:51
     * @param charater
     *            字符
     * @return I81n格式字符串
     */
    public static StringBuffer native2Ascii(char charater) {
        // 构建返回值
        StringBuffer sbf = new StringBuffer();
        if (charater > 255) {
            sbf.append("\\u");
            int lowByte = charater >>> '\b';
            sbf.append(int2HexString(lowByte));
            int highByte = charater & 0xFF;
            sbf.append(int2HexString(highByte));
        } else {
            sbf.append(charater);
        }
        return sbf;
    }

    /**
     * 将整型数转换为二进制字符串
     * 
     * @author 刘虻 2008-12-18下午06:16:19
     * @param code
     *            整型数
     * @return 二进制字符串
     */
    public static String int2HexString(int code) {
        // 转换为二进制字符串
        String hexString = Integer.toHexString(code);
        if (hexString.length() == 1) {
            hexString = "0" + hexString;
        }
        return hexString;
    }
    
    
    /**
     * 将新增的字符串放入用指定分隔符分割的字符串中（如果已存在的话，就不添加）
     * 比如： source:   aaa,bbb,ccc   addStr:  bbb    返回： aaa,bbb,ccc
     *             source:   aaa,bbb,ccc   addStr:  ddd    返回： aaa,bbb,ccc,ddd
     *                
     * @param source 源字符串
     * @param addStr 待新增字符串
     * @param split 分割符，默认为逗号
     * @return 新增后的字符串
     * 2015年4月8日
     * @author 马宝刚
     */
    public static String addSplitStr(String source,String addStr,String... split) {
        if(addStr==null || addStr.length()<1) {
            if(source==null) {
                return source;
            }
            return source;
        }
        if(source==null || source.length()<1) {
            return addStr;
        }
        String sStr = null; //分隔符
        if(split!=null && split.length>0 && split[0]!=null) {
            sStr = split[0];
        }else {
            sStr = ",";
        }
        if(source.startsWith(sStr)) {
            source = source.substring(1);
        }
        if(!source.endsWith(sStr)) {
            source += sStr;
        }
        if((sStr+source).indexOf(sStr+addStr+sStr)<0) {
            source += addStr;
        }
        return source;
    }

    /**
     * 字符编码转换为字符
     * 
     * @author 刘虻 2008-12-25下午07:00:40
     * @param str
     *            i18n字符串
     * @return utf-8格式的字符串
     */
    public static String ascii2Native(String str) {

        if (str == null) {
            return "";
        }
        String hex = "0123456789ABCDEF"; // 二进制元素
        // 构建返回值
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < str.length(); i++) {
            // 字符元素
            char c = str.charAt(i);
            if (c == '\\' && i + 1 <= str.length() && str.charAt(i + 1) == '\\') {
                buf.append("\\\\");
                i += 1;
            } else if (c == '\\' && i + 6 <= str.length()
                    && str.charAt(i + 1) == 'u') {

                String sub = str.substring(i + 2, i + 6).toUpperCase();
                int i0 = hex.indexOf(sub.charAt(0));
                int i1 = hex.indexOf(sub.charAt(1));
                int i2 = hex.indexOf(sub.charAt(2));
                int i3 = hex.indexOf(sub.charAt(3));

                if (i0 < 0 || i1 < 0 || i2 < 0 || i3 < 0) {
                    buf.append("\\u");
                    i += 1;
                } else {
                    byte[] data = new byte[2];
                    data[0] = int2Byte(i1 + i0 * 16);
                    data[1] = int2Byte(i3 + i2 * 16);
                    try {
                        buf.append(new String(data, StandardCharsets.UTF_16BE));
                    } catch (Exception ex) {
                        buf.append("\\u" + sub);
                    }
                    i += 5;
                }
            } else {
                buf.append(c);
            }
        }
        return buf.toString();
    }
    
    //#region charCount(str,ch) 计算字符串中，某个字符出现次数
    /**
     * 计算字符串中，某个字符出现次数
     * @param str  指定字符串
     * @param ch   指定字符
     * @return     出现次数
     * 2024年8月12日
     * @author MBG
     */
    public static int charCount(String str,char ch) {
    	if(str==null || str.length()<1) {
    		return 0;
    	}
    	int    reCount = 0;
    	char[] chs     = str.toCharArray();
    	for(int i=0;i<chs.length;i++) {
    		if(chs[i]==ch) {
    			reCount++;
    		}
    	}
    	return reCount;
    }
    //#endregion

    /**
     * 字符编码转为字符
     * 
     * @author 刘虻 2008-12-25下午07:05:58
     * @param i
     *            字符编码
     * @return 字符
     */
    protected static byte int2Byte(int i) {
        return (byte) ((i > 127) ? i - 256 : i);
    }

    /**
     * 根据检测类型调整参数值
     * 
     * @author 刘虻 2009-7-29下午03:13:42
     * @param checkType
     *            检测类型
     * 
     *            date 只显示年月日 trim 去掉前后空格 showint 格式化数字信息（通常用在金额数据，比如
     *            1,233,333.33 time 只显示小时分秒 datemd 只显示月日 date:[yyyy-MM-dd
     *            hh:mm:ss SSS] 按照指定格式输出年月日 cut:20:... 剪切前20个字符，并且在后面加上 ...
     *            float:16:4 格式化小数 head:字符串 最终的值为 字符串+字段值 foot:字符串 最终的值为 字段值+字符串
     *            
     *            支持多检测类型，用 |||分割
     * 
     * @param value
     *            参数值
     * @return 调整后的参数值
     */
    public static String checkValue(String checkType, String value,
            IViewHandler vh) {
        if (checkType == null || checkType.length() < 1) {
            return value;
        }
        // 会移除嵌套调用动作的页面中的处理类型,所以屏蔽掉该代码，并不影响页面外观
        // vdh.removeAttribute(IHtmlConst.ATTRIB_FIX_VALUE); //移除处理类型
        value = SString.valueOf(value); // 整理字符串
        //checkType 是不能全转换成小写的，因为格式化年月日时，需要判断内容的大小写
        String cType = SString.valueOf(checkType);
        //分割成多个检测符
        List<String> cTypeList = BaseUtil.splitToList(cType,"|||");
        boolean hasIfCheck = false; //是否包含了判断
        for(String ele:cTypeList) {
            if ("date".equals(ele)) {
                // 只显示年月日
                if (value.length() > 0) {
                    value = (new SDate(value)).getOnlyDate();
                }
            } else if (ele.startsWith("date:[")) {
                // 按照指定格式输出年月日
                String format = checkType.substring(6);
                int point = format.lastIndexOf("]"); // 分隔符
                if (point > 0) {
                    format = format.substring(0, point);
                }
                format = BaseUtil.trim(format, " ", "\t", "\"", "'\r", "\n");
                value = SDate.formatDate(value, format);
            } else if ("trim".equals(ele)) {
                // 去掉首尾空格
                value = value.trim();
            } else if ("showint".equals(ele)) {
                // 格式化整型数据 3,124,344,123
                value = SInteger.showStringValueOf(value);
            } else if ("time".equals(ele)) {
                // 只显示小时分秒
                if (value.length() > 0) {
                    value = (new SDate(value)).getOnlyTime();
                }
            } else if ("datemd".equals(ele)) {
                // 只显示月日
                if (value.length() > 0) {
                    value = (new SDate(value)).getOnlyMonthDay();
                }
            } else if (ele.indexOf("switch:") == 0) {
                // 根据数据值，按照约定替换为指定字符
                // 1:是;2:否
                checkType = checkType.substring(7);
                // 获取对照表
                Map<String, String> infoMap = fixStringToMap(checkType, ";", ":");
                if(infoMap.containsKey(value)) {
                    value = SString.valueOf(infoMap.get(value));
                }
            } else if (ele.indexOf("b64") == 0 || ele.indexOf("d64") == 0) {
                // 进行base64解码
            	if(value.startsWith("@b64@")) {
                	int point = ele.indexOf(":"); //分隔符
                	String enc; //编码格式
                	if(point>0) {
                		enc = ele.substring(point+1).trim();
                	}else {
                		enc = "UTF-8";
                	}
            		value = Base64.base64Decode(value.substring(5),enc);
            	}
            } else if (ele.indexOf("e64") == 0) {
                // 进行base64编码
            	if(!value.startsWith("@b64@")) {
                	int point = ele.indexOf(":"); //分隔符
                	String enc; //编码格式
                	if(point>0) {
                		enc = ele.substring(point+1).trim();
                	}else {
                		enc = "UTF-8";
                	}
            		value = "@b64@"+Base64.base64Encode(value,enc);
            	}
            } else if (ele.indexOf("cut:") == 0) {
                // cut:20:... 截取前20个字符，并且在尾部加...
                checkType = checkType.substring(4);
                int toLength = checkType.indexOf(":");
                // 附加字符串
                String addStr = null;
                if (toLength < 0) {
                    toLength = checkType.length();
                    addStr = "";
                } else {
                    addStr = checkType.substring(toLength + 1);
                }
                // 获取截取长度
                int cutPoint = SInteger.valueOf(checkType.substring(0, toLength));
                // 切除超出范围的字符(切除内容不包含html)
                value = StringUtil.cutHtmlString(value, cutPoint, addStr);
            }else if(ele.indexOf("swap:")==0) {
                //swap:3:***** 将结果字符串，从第3个字符后开始的字符，替换成*****
                checkType = checkType.substring(5);
                if(checkType.startsWith("[")) {
                	//swap:[key1:swap1][key2:swap2][key3:swap3]
                	int cutPoint = checkType.indexOf("[");
                	int endPoint = checkType.indexOf("]");
                	int swapPoint;
                	String subEle;
                	while(cutPoint>-1 && endPoint>0) {
                		subEle = checkType.substring(cutPoint+1,endPoint);
                		checkType = checkType.substring(endPoint+1);
                		swapPoint = subEle.indexOf(":");
                		if(swapPoint>0) {
                			value = BaseUtil.swapString(
                					value
                					,subEle.substring(0,swapPoint)
                					,subEle.substring(swapPoint+1));
                		}
                		cutPoint = checkType.indexOf("[");
                		endPoint = checkType.indexOf("]");
                	}
                }else {
                    int toLength = checkType.indexOf(":");
                    if(toLength>0) {
                        //第n个字符后开始替换
                        int startCount = SInteger.valueOf(checkType.substring(0,toLength));
                        checkType = checkType.substring(toLength+1);
                        if(value.length()>startCount) {
                            //整理后的字符串
                            String newValue = value.substring(0,startCount);
                            value = value.substring(startCount);
                            if(value.length()>checkType.length()) {
                                //实现成 139******001
                                value = newValue+checkType+value.substring(checkType.length()+value.length());
                            }else {
                                //长度不够，实现成 139********
                                value = newValue+checkType;
                            }
                        }else {
                            //长度完全不够，实现成 **********
                            value = checkType;
                        }
                    }
                }
            } else if (ele.indexOf("float:") == 0) {
                // 处理浮点数 float:4 将数字转换为 小数4位
                // 除去float:
                checkType = checkType.substring(6);
                // 位置
                int toLength = checkType.indexOf(":");
                int pointLength = 0; // 小数点位数
                if (toLength > 0) {
                    pointLength = SInteger.valueOf(checkType.substring(toLength+1));
                } else {
                    pointLength = SInteger.valueOf(checkType);
                }
                try {
                	value = SDouble.stringValueOf(value,pointLength);
                } catch (Exception e) {
                    value = "--";
                }
            } else if (ele.indexOf("double:") == 0) {
                // 处理双精度数 double:4 将数字转换为 小数4位
                // 除去float:
                checkType = checkType.substring(7);
                // 位置
                int toLength = checkType.indexOf(":");
                int pointLength = 0; // 小数点位数
                if (toLength > 0) {
                    pointLength = SInteger.valueOf(checkType.substring(toLength+1));
                } else {
                    pointLength = SInteger.valueOf(checkType);
                }
                try {
                    value = SDouble.stringValueOf(value,pointLength);
                } catch (Exception e) {
                    value = "--";
                }
            } else if (ele.indexOf("head:") == 0) {
                // head:字符串 最终的值为 字符串+字段值
                return checkType.substring(5) + value;
            } else if (ele.indexOf("foot:") == 0) {
                // foot:字符串 最终的值为 字段值+字符串
                return value + checkType.substring(5);
            } else if ("tohtml".equals(ele)) {
                // 将文本转换为HTML格式
                return fixHtmlString(value);
            } else if (ele.startsWith("if:")) {
                /*
                 * if:value{srcattrib:objattrib}
                 * 如果数据值为value，则将srcattrib属性名改为objattrib 或者 if:value{hidden}
                 * 如果条件成立，就隐藏 或者 if:value{!hidden} 如果条件不成立，就隐藏 value 前缀 >
                 * 大于value时条件生效 < 小于value时条件生效 >= 同上，你懂的 <= <> || 被value整除
                 * (包含的值，用逗号分割)
                 * _field="id" _check="if:<>2{attr1:attr2}   如果id值不等于2，将属性attr1值，替换为attr2值
                 * 
                 * <span _field="id" _check="if:<>{attr1}  attr1="有">无</span>  如果id值不等于空，将属性attr1的值覆盖 span的text
                 */
            	hasIfCheck = true;
                // 条件触发
                checkType = checkType.substring(3);
                int point = checkType.lastIndexOf("{"); // 检测分隔符
                if (point < 0) {
                    return null;
                }
                // 原属性名
                String srcAttr = checkType.substring(point + 1);
                checkType = checkType.substring(0, point);
                // 目标属性名
                String objAttr = "";
                point = srcAttr.lastIndexOf("}");
                if (point > 0) {
                    srcAttr = srcAttr.substring(0, point);
                }
                boolean hidden = false; //条件成立时隐藏
                boolean unHidden = false;  //条件不成立时隐藏
                if ("hidden".equals(srcAttr.toLowerCase())) {
                    hidden = true;
                    srcAttr = "";
                } else if ("!hidden".equals(srcAttr.toLowerCase())) {
                    unHidden = true;
                    srcAttr = "";
                } else {
                    point = srcAttr.lastIndexOf(":");
                    if (point < 0) {
                        objAttr = "";
                    }else {
                        objAttr = srcAttr.substring(point + 1);
                        srcAttr = srcAttr.substring(0, point);
                    }
                }
                String checkValue; // 检测值
                if (checkType.startsWith(">=")) {
                    checkValue = checkType.substring(2);
                    if (SDouble.valueOf(value) >= SDouble.valueOf(checkValue)) {
                        if(hidden) {
                            vh.oa(false);
                        }else {
                            if(srcAttr.length()>0) {
                                if(objAttr.length()>0) {
                                    vh.ra(objAttr);
                                    vh.rna(srcAttr, objAttr);
                                }else {
                                    vh.nt(vh.ra(srcAttr));
                                }
                            }
                        }
                    } else {
                        if(unHidden) {
                            vh.oa(false);
                        }else {
                            if(srcAttr.length()>0){
                                vh.ra(srcAttr);
                            }
                        }
                    }
                } else if (checkType.startsWith("<=")) {
                    checkValue = checkType.substring(2);
                    if (SDouble.valueOf(value) <= SDouble.valueOf(checkValue)) {
                        if(hidden) {
                            vh.oa(false);
                        }else {
                            if(srcAttr.length()>0) {
                                if(objAttr.length()>0) {
                                    vh.ra(objAttr);
                                    vh.rna(srcAttr, objAttr);
                                }else {
                                    vh.nt(vh.ra(srcAttr));
                                }
                            }
                        }
                    } else {
                        if(unHidden) {
                            vh.oa(false);
                        }else {
                            if(srcAttr.length()>0){
                                vh.ra(srcAttr);
                            }
                        }
                    }
                } else if (checkType.startsWith("<>") || checkType.startsWith("!=")) {
                    checkValue = checkType.substring(2);
                    if (!value.equals(checkValue)) {
                        if(hidden) {
                            vh.oa(false);
                        }else {
                            if(srcAttr.length()>0) {
                                if(objAttr.length()>0) {
                                    vh.ra(objAttr);
                                    vh.rna(srcAttr, objAttr);
                                }else {
                                    vh.nt(vh.ra(srcAttr));
                                }
                            }
                        }
                    } else {
                        if(unHidden) {
                            vh.oa(false);
                        }else {
                            if(srcAttr.length()>0){
                                vh.ra(srcAttr);
                            }
                        }
                    }
                } else if (checkType.startsWith("<")) {
                    checkValue = checkType.substring(1);
                    if (SDouble.valueOf(value) < SDouble.valueOf(checkValue)) {
                        if(hidden) {
                            vh.oa(false);
                        }else {
                            if(srcAttr.length()>0) {
                                if(objAttr.length()>0) {
                                    vh.ra(objAttr);
                                    vh.rna(srcAttr, objAttr);
                                }else {
                                    vh.nt(vh.ra(srcAttr));
                                }
                            }
                        }
                    } else {
                        if(unHidden) {
                            vh.oa(false);
                        }else {
                            if(srcAttr.length()>0){
                                vh.ra(srcAttr);
                            }
                        }
                    }
                } else if (checkType.startsWith(">")) {
                    checkValue = checkType.substring(1);
                    if (SDouble.valueOf(value) > SDouble.valueOf(checkValue)) {
                        if(hidden) {
                            vh.oa(false);
                        }else {
                            if(srcAttr.length()>0) {
                                if(objAttr.length()>0) {
                                    vh.ra(objAttr);
                                    vh.rna(srcAttr, objAttr);
                                }else {
                                    vh.nt(vh.ra(srcAttr));
                                }
                            }
                        }
                    } else {
                        if(unHidden) {
                            vh.oa(false);
                        }else {
                            if(srcAttr.length()>0){
                                vh.ra(srcAttr);
                            }
                        }
                    }
                } else if (checkType.startsWith("==")) {
                    checkValue = checkType.substring(2);
                    if (value.equals(checkValue)) {
                        if(hidden) {
                            vh.oa(false);
                        }else {
                            if(srcAttr.length()>0) {
                                if(objAttr.length()>0) {
                                    vh.ra(objAttr);
                                    vh.rna(srcAttr, objAttr);
                                }else {
                                    vh.nt(vh.ra(srcAttr));
                                }
                            }
                        }
                    } else {
                        if(unHidden) {
                            vh.oa(false);
                        }else {
                            if(srcAttr.length()>0){
                                vh.ra(srcAttr);
                            }
                        }
                    }
                } else if (checkType.startsWith("=")) {
                    checkValue = checkType.substring(1);
                    if (value.equals(checkValue)) {
                        if(hidden) {
                            vh.oa(false);
                        }else {
                            if(srcAttr.length()>0) {
                                if(objAttr.length()>0) {
                                    vh.ra(objAttr);
                                    vh.rna(srcAttr, objAttr);
                                }else {
                                    vh.nt(vh.ra(srcAttr));
                                }
                            }
                        }
                    } else {
                        if(unHidden) {
                            vh.oa(false);
                        }else {
                            if(srcAttr.length()>0){
                                vh.ra(srcAttr);
                            }
                        }
                    }
                } else if (checkType.startsWith("||")) {
                    // 是否能被整除
                    checkValue = checkType.substring(2);
                    int testInt1 = SInteger.valueOf(value);
                    int testInt2 = SInteger.valueOf(checkValue);
                    // 整除值
                    int testInt = testInt1 / testInt2;
                    if (testInt1 == (testInt2 * testInt)) {
                        if(hidden) {
                            vh.oa(false);
                        }else {
                            if(srcAttr.length()>0) {
                                if(objAttr.length()>0) {
                                    vh.ra(objAttr);
                                    vh.rna(srcAttr, objAttr);
                                }else {
                                    vh.nt(vh.ra(srcAttr));
                                }
                            }
                        }
                    } else {
                        if(unHidden) {
                            vh.oa(false);
                        }else {
                            if(srcAttr.length()>0){
                                vh.ra(srcAttr);
                            }
                        }
                    }
                } else if (checkType.startsWith("(")) {
                    // 是否包含指定值
                    checkValue = checkType.substring(1);
                    point = checkValue.lastIndexOf(")");
                    if (point < 0) {
                        return null;
                    }
                    // 包含值序列
                    List<String> checkList = BaseUtil.splitToList(
                            checkValue.substring(0, point), ",");
                    if (checkList.contains(value)) {
                        if(hidden) {
                            vh.oa(false);
                        }else {
                            if(srcAttr.length()>0) {
                                if(objAttr.length()>0) {
                                    vh.ra(objAttr);
                                    vh.rna(srcAttr, objAttr);
                                }else {
                                    vh.nt(vh.ra(srcAttr));
                                }
                            }
                        }
                    } else {
                        if(unHidden) {
                            vh.oa(false);
                        }else {
                            if(srcAttr.length()>0){
                                vh.ra(srcAttr);
                            }
                        }
                    }
                } else {
                    if (value.equals(checkType) || ("[NULL]".equals(checkType) && value.length()<1)) {
                        if(hidden) {
                            vh.oa(false);
                        }else {
                            if(srcAttr.length()>0) {
                                if(objAttr.length()>0) {
                                    vh.ra(objAttr);
                                    vh.rna(srcAttr, objAttr);
                                }else {
                                    vh.nt(vh.ra(srcAttr));
                                }
                            }
                        }
                    } else {
                        if(unHidden) {
                            vh.oa(false);
                        }else {
                            if(srcAttr.length()>0){
                                vh.ra(srcAttr);
                            }
                        }
                    }
                }
            }
        }
        if(hasIfCheck) {
        	return null;
        }
        return value;
    }

    /**
     * 将字符串分割为Map格式
     * 
     * @param str
     *            字符串 1:是;0:否;:否
     * @param eleSpec
     *            元素分隔符 ;
     * @param keySpec
     *            信息分隔符
     * @return 整理后的容器 2014年3月29日
     * @author 马宝刚
     */
    public static Map<String, String> fixStringToMap(String str,
            String eleSpec, String keySpec) {
        // 构建返回值
        HashMap<String, String> reMap = new HashMap<String, String>();
        if (str == null) {
            return reMap;
        }
        str = str.trim();
        if (str.length() < 1) {
            return reMap;
        }
        // 将字符串分割为元素数组
        String[] eles = str.split(eleSpec);
        String[] infos = null; // 元素信息
        for (int i = 0; i < eles.length; i++) {
            infos = eles[i].split(keySpec);
            if (infos.length > 1) {
                reMap.put(infos[0], infos[1]);
            }
        }
        return reMap;
    }

    /**
     * 将url参数字符串转换为参数容器 刘虻 2011-5-4 下午02:50:25
     * 
     * @param queryString
     *            url参数字符串
     * @return 参数容器
     */
    public static Map<String, String> fixQueryString(String queryString) {
        int noKeyCount = 0; //没有参数主键的参数值数量
        // 构建返回值
        HashMap<String, String> reMap = new HashMap<String, String>();
        if (queryString == null || queryString.length() < 1) {
            return reMap;
        }
        String[] params = queryString.split("&");
        int point = 0; // 分割点
        for (int i = 0; i < params.length; i++) {
            point = params[i].indexOf("=");
            if (point > -1) {
                reMap.put(params[i].substring(0, point),
                        params[i].substring(point + 1));
            }else {
                //注意，咱们支持无主键参数值，就是牛逼，爱咋咋地
                reMap.put("_no_key_"+noKeyCount++,params[i]);
            }
        }
        if(noKeyCount>0) {
            //顺便放入无主键参数的数量
            reMap.put("_no_key_count_",String.valueOf(noKeyCount));
        }
        return reMap;
    }
    
    /**
     * 将url参数字符串转换为参数容器 刘虻 2011-5-4 下午02:50:25
     * 
     * @param queryString
     *            url参数字符串
     * @return 参数容器
     */
    public static Map<String, String[]> fixQueryStrings(String queryString) {
        int noKeyCount = 0; //没有参数主键的参数值数量
        // 构建返回值
        HashMap<String, String[]> reMap = new HashMap<String, String[]>();
        if (queryString == null || queryString.length() < 1) {
            return reMap;
        }
        String[] params = queryString.split("&");
        int point = 0; // 分割点
        for (int i = 0; i < params.length; i++) {
            point = params[i].indexOf("=");
            if (point > -1) {
                reMap.put(params[i].substring(0, point),
                        new String[] {params[i].substring(point + 1)});
            }else {
                //注意，咱们支持无主键参数值，就是牛逼，爱咋咋地
                reMap.put("_no_key_"+noKeyCount++,new String[] {params[i]});
            }
        }
        if(noKeyCount>0) {
            //顺便放入无主键参数的数量
            reMap.put("_no_key_count_",new String[] {String.valueOf(noKeyCount)});
        }
        return reMap;
    }

    /**
     * 将字符串序列转换为字符串（用逗号分割） 刘虻 2013-2-1 下午3:29:16
     * 
     * @param list
     *            字符串序列
     * @return 字符串（用逗号分割）
     */
    public static String getListString(List<String> list) {
        if (list == null) {
            return "";
        }
        // 构建返回值
        StringBuffer reSbf = new StringBuffer();
        boolean noFirst = false; // 是否为非首次循环
        String ele; // 元素
        for (int i = 0; i < list.size(); i++) {
            ele = SString.valueOf(list.get(i));
            if (ele.length() > 0) {
                if (noFirst) {
                    reSbf.append(",");
                }
                reSbf.append(ele);
                if (!noFirst) {
                    noFirst = true;
                }
            }
        }
        return reSbf.toString();
    }

    /**
     * 分割方法，比如将字符串 aa,bb,"c,d",ee,f<g,h> 分割， 但将 c,d 或<g,h> 作为一个元素（并不按照其中的逗号进行分割）
     * 段值： c,d 或 <g,h> 为段值，并不解析段值中的分割字符
     * 
     * @param content   待处理的字符串
     * @param splitChar 需要作为分割的字符
     * @param sExcepts  段值开始字符数组
     * @param tExcepts  对应的段值结束字符数组
     * @return 分割后的字符串序列 2015年1月22日
     * @author 马宝刚
     */
    public static List<String> split(String content, String splitChar,
            String[] sExcepts, String[] tExcepts) {
        // 构建返回值
        List<String> resList = new ArrayList<String>();

        int fPoint = 0; // 开始分割位置
        int point; // 分隔符所在的位置
        int[] ePoints; // 被包含值开始符所在的位置
        while (true) {
            point = content.indexOf(splitChar, fPoint);
            ePoints = getMinPoint(content, sExcepts, tExcepts);
            if (point < 0) {
                break;
            }
            if (ePoints[0] > -1 && ePoints[0] < point && ePoints[1] > point) {
                // 分隔符包含在段值内
                fPoint = point + splitChar.length();
                continue;
            }
            resList.add(content.substring(0, point));
            content = content.substring(point + splitChar.length()
            );
            fPoint = 0;
        }
        if (content.length() > 0) {
            resList.add(content);
        }
        return resList;
    }

    /**
     * 内部方法，根据段值开始字符数组，和结束字符数组，返回一个最小的段值开始位置
     * 
     * @param content
     *            待处理的字符串
     * @param sChars
     *            段值开始字符数组
     * @param tChars
     *            对应的段值结束字符数据
     * @return 最小的段值起始位置 2015年1月22日
     * @author 马宝刚
     */
    private static int[] getMinPoint(String content, String[] sChars,
            String[] tChars) {
        int[] rePoints = new int[2]; // 构建返回值
        rePoints[0] = -1;
        rePoints[1] = -1;
        int point; // 当前处理的位置值
        int tPoint; // 结束符所在的位置
        if (content != null && content.length() > 0 && sChars != null
                && sChars.length > 0 && tChars != null
                && sChars.length == tChars.length) {
            for (int i = 0; i < sChars.length; i++) {
                point = content.indexOf(sChars[i]);
                tPoint = content.indexOf(tChars[i], point + sChars[i].length());
                if (rePoints[0] < 0
                        || (point > -1 && rePoints[0] > point && point < tPoint)) {
                    // 存在开始符，并且也存在对应的结束符
                    rePoints[0] = point;
                    rePoints[1] = tPoint;
                }
            }
        }
        return rePoints;
    }
    
    /**
     * 截取字符串指定分割点，并返回前面部分。如果没有找到分割点，返回全部
     * @param str          处理前字符串
     * @param cutPointStr  分隔符
     * @return             处理后字符串
     * 2016年10月13日
     * @author MBG
     */
    public static String cutString(String str,String cutPointStr) {
    	if(str==null || cutPointStr==null || str.length()<cutPointStr.length()) {
    		return str;
    	}
    	//分割点
    	int point = str.indexOf(cutPointStr);
    	if(point>-1) {
    		return str.substring(0,point);
    	}
    	return str;
    }
    
    
    /**
     * 将字符串数组转换为用逗号分割的字符串
     * @param arr 字符串数组
     * @return 用逗号分割的字符串
     * 2016年10月13日
     * @author MBG
     */
    public static String arr2str(String[] arr) {
    	return arr2str(arr,",");
    }
    
    
    
    /**
     * 将字符串数组转换为字符串
     * @param arr 字符串数组
     * @param str 分隔符
     * @return 字符串
     * 2016年10月13日
     * @author MBG
     */
    public static String arr2str(Object[] arr,String str) {
    	if(str==null || str.length()<1) {
    		str = ",";
    	}
    	//构建返回值
    	StringBuffer sbf = new StringBuffer();
    	if(arr!=null) {
    		String ele;
    		for(int i=0;i<arr.length;i++) {
    			ele = arr[i]==null?null:arr[i].toString();
    			if(ele==null || ele.length()<1) {
    				continue;
    			}
    			if(sbf.length()>0) {
    				sbf.append(str);
    			}
    			sbf.append(arr[i]);
    		}
    	}
    	return sbf.toString();
    }
    
    
    
    
    
    /**
     * 将字符串序列转换为逗号分隔的字符串
     * @param list 字符串序列
     * @return 用逗号分隔的元素字符串
     * 2016年12月1日
     * @author MBG
     */
    public static String list2str(List<String> list) {
    	return list2str(list,",");
    }
    
    
    /**
     * 将字符串序列转换为逗号分隔的字符串
     * @param list  字符串序列
     * @param str   分隔符
     * @return      用逗号分隔的元素字符串
     * 2019年1月18日
     * @author MBG
     */
    public static String list2str(List<String> list,String str) {
    	if(str==null || str.length()<1) {
    		str = ",";
    	}
    	//构建返回值
    	StringBuffer sbf = new StringBuffer();
    	if(list!=null) {
    		String ele; //元素
    		for(int i=0;i<list.size();i++) {
    			ele = list.get(i);
    			if(ele==null || ele.length()<1) {
    				continue;
    			}
    			if(sbf.length()>0) {
    				sbf.append(str);
    			}
    			sbf.append(ele);
    		}
    	}
    	return sbf.toString();
    }
    
    
    /**
     * 用于数据库语句拼接提交值。 生成插入值标识    ?,?,?,?
     * @param list 待提交值
     * @return 插入值标识
     * 2017年1月17日
     * @author MBG
     */
    public static String list2DbProp(List<String> list) {
    	//构建返回值
    	StringBuffer sbf = new StringBuffer();
    	if(list!=null) {
    		for(int i=0;i<list.size();i++) {
    			if(i>0) {
    				sbf.append(",");
    			}
    			sbf.append("?");
    		}
    	}
    	return sbf.toString();
    }
    
    /**
     * 将数组，或者字符串参数存放到一个数组中并返回
     * @param subArr 数据或字符串参数
     * @return 整理后的数组
     * 2017年1月17日
     * @author MBG
     */
    @SuppressWarnings("rawtypes")
	public static String[] sumArray(Object... subArr) {
    	//构建返回值
    	List<String> reList = new ArrayList<String>();
    	if(subArr!=null) {
    		for(int i=0;i<subArr.length;i++) {
    			if(subArr[i] instanceof String) {
    				reList.add((String)subArr[i]);
    			}else if(subArr[i] instanceof String[]){
    				for(int j=0;j<((String[])subArr[i]).length;j++) {
    					reList.add(SString.valueOf(((String[])subArr[i])[j]));
    				}
    			}else if(subArr[i] instanceof Object[]){
    				for(int j=0;j<((Object[])subArr[i]).length;j++) {
    					reList.add(SString.valueOf(((Object[])subArr[i])[j]));
    				}
    			}else if(subArr[i] instanceof Collection){
    				for(Object ele:((Collection)subArr[i])) {
    					reList.add(SString.valueOf(ele));
    				}
    			}else {
    				reList.add(SString.valueOf(subArr[i]));
    			}
    		}
    	}
    	//构建数组返回值
    	String[] reArrs = new String[reList.size()];
    	reList.toArray(reArrs);
    	return reArrs;
    }
    
    
    
    /**
     * 将字符串序列转换为字符串数组
     * @param list 字符串序列
     * @return 字符串数组
     * 2016年12月14日
     * @author MBG
     */
    public static String[] list2strs(List<String> list) {
    	if(list==null) {
    		return new String[0];
    	}
    	//构建返回值
    	String[] res = new String[list.size()];
    	for(int i=0;i<list.size();i++) {
    		res[i] = list.get(i);
    	}
    	return res;
    }
    
    /**
     * 将字符串数组转换为字符串序列
     * @param arrs 字符串数组
     * @return 字符串序列
     * 2016年12月14日
     * @author MBG
     */
    public static List<String> strs2list(Object[] arrs){
    	//构建返回值
    	List<String> reList = new ArrayList<String>();
    	if(arrs!=null && arrs.length>0) {
    		for(int i=0;i<arrs.length;i++) {
    			reList.add(arrs[i]==null?null:arrs[i].toString());
    		}
    	}
    	return reList;
    }
    
    /**
     * 获取指定长度的随机字符串
     * @param length 字符串长度
     * @return 随机字符串
     * 2016年11月18日
     * @author MBG
     */
    public static String random(int length) {
    	//含有字符和数字的字符串
        String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random = new Random();//随机类初始化
        StringBuffer sb = new StringBuffer();//StringBuffer类生成，为了拼接字符串
        int randStrLength = str.length(); //字典长度
        for (int i=0; i<length; ++i) {
            sb.append(str.charAt(random.nextInt(randStrLength)));
        }
        return sb.toString();
    }
    
    /**
     * 获取指定长度的数字随机字符串
     * @param length 指定长度
     * @return       返回字符串
     * 2018年12月3日
     * @author MBG
     */
    public static String numRandom(int length) {
    	//含有字符和数字的字符串
        String str = "0123456789";
        Random random = new Random();//随机类初始化
        StringBuffer sb = new StringBuffer();//StringBuffer类生成，为了拼接字符串
        int randStrLength = str.length(); //字典长度
        for (int i=0; i<length; ++i) {
            sb.append(str.charAt(random.nextInt(randStrLength)));
        }
        return sb.toString();
    }
    
    
    /**
     * 判断是否为纯数字
     * @param str 待判断字符串
     * @return 是否为纯数字
     * 2017年1月16日
     * @author MBG
     */
    public static boolean isInt(String str) {
    	if(str==null || str.length()<1) {
    		return false;
    	}
        return str.matches("^\\d+$$");  
    }  
    
    
    /**
     * 判断是否为纯数字
     * @param str 待判断字符串
     * @return 是否为纯数字
     * 2017年1月16日
     * @author MBG
     */
    public static boolean isNumber(String str) {
    	if(str==null || str.length()<1) {
    		return false;
    	}
        return str.matches("-?(0|[1-9]\\d*)(\\.\\d+)?");  
    }  
    
    /**
     * 指定字符subStr出现在content中的次数
     * @param content 被搜索的字符串
     * @param subStr  指定字符
     * @return        出现次数
     * 2018年5月4日
     * @author MBG
     */
    public static int inStrCount(String content,String subStr) {
    	if(content==null || content.length()<1 || subStr==null || subStr.length()<1) {
    		return 0;
    	}
		int count = 0; //统计到的字符出现次数
		int point = content.indexOf(subStr); //字符出现位置
		while(point>-1) {
			count++;
			point = content.indexOf(subStr,point+1);
		}
		return count;
    }
    
    /**
     * 从包含数字的字符串中提取出数字
     * @param str 包含数字的字符串
     * @return 提取到的数字
     * 2018年6月5日
     * @author MBG
     */
    public static int getIntFromString(String str) {
    	if(str==null || str.length()<1) {
    		return 0;
    	}
    	String numStr = ""; //筛选出的数字字符串
    	char ele; //字符元素
    	for(int i=0;i<str.length();i++){
    		ele = str.charAt(i);
    		if(ele>=48 && ele<=57 || (ele=='-' && i==0)){
    			numStr+=str.charAt(i);
    		}
    	}
    	try {
    		return Integer.parseInt(numStr);
    	}catch(Exception e) {}
    	return 0;
    }
    

    /**
     * 测试入口
     * 
     * @author 刘虻 2007-6-22下午04:25:22
     * @param args
     *            导入参数
     */
    public static void main(String[] args) {
        try {

        	int columnIndex = 27;

            String columnStr = "";
            do {
                /* 索引从0开始，如果不减1，从倒数第二位向前都会递加一位
                如730，减一是ABC，不减是BCC */
                if (columnStr.length() > 0) {
                    columnIndex--;
                }

                columnStr = ((char) (columnIndex % 26 + (int) 'A')) + columnStr;
                columnIndex = (int) ((columnIndex - columnIndex % 26) / 26);
            } while (columnIndex > 0);
            
        	System.out.println(columnStr);
        	
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    
    /**
     * 将Excel列索引值转换为列名，比如 0为A 1为B  26为AA
     * @param columnIndex 列索引值（从0开始）
     * @return            列名
     * 2022年1月27日
     * @author MBG
     */
    public static String getExcelColumnName(int columnIndex) {
    	String columnStr = "";
    	do {
    		/* 索引从0开始，如果不减1，从倒数第二位向前都会递加一位
            如730，减一是ABC，不减是BCC */
    		if (columnStr.length() > 0) {
    			columnIndex--;
    		}
    		columnStr   = ((char) (columnIndex % 26 + (int) 'A')) + columnStr;
    		columnIndex = (int) ((columnIndex - columnIndex % 26) / 26);
    	} while (columnIndex > 0);
    	return columnStr;
    }
    
    /**
     * 随机生成64位字符串
     * @return  64位字符串
     */
    public static String randomStr(int size) {
    	//字典字符串
    	String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    	//构建随机处理类
    	Random random = new Random();
    	//构建返回值
    	StringBuffer sb = new StringBuffer();
    	for (int i=0; i<size; i++) {
    		int number = random.nextInt(base.length());
    		sb.append(base.charAt(number));
    	}
    	return sb.toString();
    }
    
	/**
	 * 把 ||u 开头的单字转成汉字，如 |u6B65 ->　步
	 * @param str
	 * @return
	 */
	private static String ucharToCn(String str) {
	  StringBuilder sbf   = new StringBuilder().append("0x").append(str, 2, 6);
	  Integer codeInteger = Integer.decode(sbf.toString());
	  return String.valueOf((char)codeInteger.intValue());
	}
	
	
	/**
	 * 字符串是否以Unicode字符开头。约定Unicode字符以 |u开头。
	 * @param str 字符串
	 * @return true表示以Unicode字符开头.
	 */
	private static boolean isCharWithUnicode(String str,String matchChars) {
		if (str==null || str.length()<1) {
			return false;
		}
		if (!str.startsWith(matchChars) 
				&& !str.startsWith(matchChars.toUpperCase())) {
			return false;
		}
		if (str.length() < (matchChars.length()+4)) {
			return false;
		}
		return Pattern.matches(pattern,str.substring(matchChars.length(), matchChars.length()+4));
	}
	
	
	/**
	 * 字符串中，所有以 \\u值开头的UNICODE字符串，全部替换成汉字
	 * @param str         待转换字符串
	 * @return            转义后的UNICODE字符串
	 * 2019年11月22日
	 * @author MBG
	 */
	public static String unicodeToStr(String str) {
		return unicodeToStr(str,"\\u");
	}
	
	
	/**
	 * 字符串中，所有以 matchChars值开头的UNICODE字符串，全部替换成汉字
	 * @param str         待转换字符串
	 * @param matchChars  需要转换的UNICODE代码开头部分，比如\\u  |u
	 * @return            转义后的UNICODE字符串
	 * 2019年11月22日
	 * @author MBG
	 */
	public static String unicodeToStr(String str,String matchChars) {
	  if(str==null){
	    return "";
	  }
	  if(matchChars==null) {
		  matchChars = "\\u";
	  }else {
		  matchChars = matchChars.toLowerCase();
	  }
	  //用于构建新的字符串
	  StringBuilder sbf = new StringBuilder();
	  // 从左向右扫描字符串。tmpStr是还没有被扫描的剩余字符串。
	  // 下面有两个判断分支：
	  // 1. 如果剩余字符串是Unicode字符开头，就把Unicode转换成汉字，加到StringBuilder中。然后跳过这个Unicode字符。
	  // 2.反之， 如果剩余字符串不是Unicode字符开头，把普通字符加入StringBuilder，向右跳过1.
	  String tmpStr;
	  int length = str.length();
	  for (int i=0;i<length;) {
	    tmpStr = str.substring(i);
	    if (isCharWithUnicode(tmpStr,matchChars)) { // 分支1
	    	sbf.append(ucharToCn(tmpStr));
	    	i += matchChars.length()+4;
	    } else { // 分支2
	    	sbf.append(str, i, i + 1);
	    	i++;
	    }
	  }
	  return sbf.toString();
	}
	
    //#region padSpace(str,length) 字符串后面补空格
    /**
     * 字符串后面补空格
     * 注意：末尾都有\r\n
     * @param origin 需要补空格的字符串
     * @param length 最终长度
     * @return       补空格后的字符串
     */
    public static String padSpace(String str, int length) {
    	if(str==null) {
    		str = "";
    	}
    	if(str.length()>length) {
    		return str.substring(0,length);
    	}
    	// 构建返回值
    	StringBuffer reSbf = new StringBuffer(str);
    	for(int i=0;i<length-str.length();i++) {
    		reSbf.append(" ");
    	}
        return reSbf.toString();
    }
    //#endregion
	
    //#region padSpaceRN(str,length) 字符串后面补空格
    /**
     * 字符串后面补空格
     * 注意：末尾都有\r\n
     * @param origin 需要补空格的字符串
     * @param length 最终长度
     * @return       补空格后的字符串
     */
    public static String padSpaceRN(String str, int length) {
    	if(str==null) {
    		str = "";
    	}
    	if(str.length()>length) {
    		return str.substring(0,length);
    	}
    	// 构建返回值
    	StringBuffer reSbf = new StringBuffer(str);
    	for(int i=0;i<length-str.length();i++) {
    		reSbf.append(" ");
    	}
        return reSbf.append("\r\n").toString();
    }
    //#endregion

    //#region padZeroRN(str,length) 字符串前面补零
    /**
     * 字符串前面补零
     * 注意：末尾都有\r\n
     * @param val     需要补零的字符串
     * @param length  最终长度
     * @return        补零后的字符串
     */
    public static String padZeroRN(String val,int length) {
    	if(val==null) {
    		val = "";
    	}
    	// 转换成字符串
    	if(val.length()>length) {
    		return val.substring(val.length()-length);
    	}
    	// 构建补零缓存
    	StringBuffer zeroSbf = new StringBuffer();
    	for(int i=0;i<length-val.length();i++) {
    		zeroSbf.append("0");
    	}
    	return zeroSbf+val+"\r\n";
    }
    //#endregion

    //#region padZero(str,length) 字符串前面补零
    /**
     * 字符串前面补零
     * 注意：末尾都有\r\n
     * @param val     需要补零的字符串
     * @param length  最终长度
     * @return        补零后的字符串
     */
    public static String padZero(String val,int length) {
    	if(val==null) {
    		val = "";
    	}
    	// 转换成字符串
    	if(val.length()>length) {
    		return val.substring(val.length()-length);
    	}
    	// 构建补零缓存
    	StringBuffer zeroSbf = new StringBuffer();
    	for(int i=0;i<length-val.length();i++) {
    		zeroSbf.append("0");
    	}
    	return zeroSbf+val;
    }
    //#endregion
}









